 package ss.pku.jsa.type.inference;
 
 import java.util.HashMap;
import java.util.Map;

import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.IVariableBinding;
 
 @SuppressWarnings({"rawtypes","unchecked"})
public class FieldKey extends JqualKey
   implements Comparable
 {
   public TypeKey declaringType;
   public String name;
   public TypeKey type;
   private static Map<Key, FieldKey> cache = new HashMap();
 
   protected static FieldKey getFieldKey(TypeKey declaringType, String name, TypeKey type)
   {
     Profile.logMemStart("FieldKey/new FieldKey.Key");
     Key k = new Key(declaringType, name);
     Profile.logMemEnd();
 
     FieldKey ret = (FieldKey)cache.get(k);
     if (ret == null) {
       ret = new FieldKey(declaringType, name, type);
       cache.put(k, ret);
     }
     return ret;
   }
 
   public static FieldKey getFieldKey(IVariableBinding b)
   {
     if (!b.isField()) {
       throw new IllegalArgumentException("Passed " + b.getKey() + " to makeFieldKey. Should only use for fields.");
     }
     ITypeBinding t = b.getDeclaringClass();
 
     if (t == null) {
       throw new NullPointerException("Passed " + b.getKey() + " to makeFieldKey. Declaring Class is null.");
     }
     TypeKey declaringType = TypeKey.getTypeKey(t);
 
     Profile.logMemStart("FieldKey/new TypeKey");
     TypeKey type = TypeKey.getTypeKey(b.getType());
     Profile.logMemEnd();
 
     String name = b.getName();
 
     return getFieldKey(declaringType, name, type);
   }
 
   protected FieldKey(TypeKey declaringType, String name, TypeKey type) {
     this.name = name;
     this.declaringType = declaringType;
     this.type = type;
   }
   protected FieldKey() {
   }
 
   public String toString() {
     return this.name;
   }
   public String getShortName() {
     return this.name;
   }
 
   public TypeKey getDeclaringType()
   {
     return this.declaringType;
   }
 
   public int compareTo(Object o)
   {
     return toString().compareTo(o.toString());
   }
 
   public boolean treatFieldSensitively()
   {
     if ((this instanceof ArrayFieldKey))
       return false;
     if (JqualPlugin.fieldSensitive) {
       return true;
     }
 
     return (JqualPlugin.obeyFSAnnotations) && (
       (JqualPlugin.analysis.fieldSensitiveFields.contains(this)) || 
       (JqualPlugin.analysis.fieldSensitiveTypes.contains(getDeclaringType())));
   }
 
   private static class Key
   {
     public TypeKey declaringType;
     public String name;
 
     public Key(TypeKey declaringType, String name)
     {
       this.declaringType = declaringType;
       this.name = name;
     }
 
     public int hashCode()
     {
       int result = 1;
       result = 31 * result + (this.declaringType == null ? 0 : this.declaringType.hashCode());
       result = 31 * result + (this.name == null ? 0 : this.name.hashCode());
       return result;
     }
 
     public boolean equals(Object obj) {
       if (this == obj)
         return true;
       if (obj == null)
         return false;
       if (getClass() != obj.getClass())
         return false;
       Key other = (Key)obj;
       if (this.declaringType == null) {
         if (other.declaringType != null)
           return false;
       } else if (!this.declaringType.equals(other.declaringType))
         return false;
       if (this.name == null) {
         if (other.name != null)
           return false;
       } else if (!this.name.equals(other.name))
         return false;
       return true;
     }
   }
 }

